package com.devplatform.controller;

import cn.hutool.captcha.generator.MathGenerator;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.devplatform.constants.DataVoCodeConstant;
import com.devplatform.pojo.dto.ChangeEmailDto;
import com.devplatform.pojo.dto.ChangePasswordDto;
import com.devplatform.pojo.dto.DeleteDto;
import com.devplatform.pojo.user.User;
import com.devplatform.pojo.validateInt.Add;
import com.devplatform.pojo.vo.*;
import com.devplatform.service.user.IUserService;
import com.devplatform.util.EmailUtil;
import com.devplatform.util.JwtUtil;
import com.devplatform.util.MessageUtil;
import com.devplatform.util.UserContextHolder;
import jakarta.servlet.http.HttpSession;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/user")
public class UserController {
    private final IUserService userService;
    private final BCryptPasswordEncoder passwordEncoder;
    private final JwtUtil jwtUtil;
    private final EmailUtil emailUtil;
    private final MessageUtil messageUtil;

    @PostMapping("/register")
    public DataVo<String> register(@RequestBody @Validated(Add.class) RegisterVo user, HttpSession session) {
        //判断邮箱是否已绑定其他用户
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getEmail, user.getEmail());
        if (userService.getOne(queryWrapper) != null) {
            return DataVo.error(DataVoCodeConstant.USER_IS_EXIST, "邮箱已绑定其他用户");
        }

        // 校验邮件验证码
        DataVo<String> dataVo = emailUtil.checkEmailCode(session, user.getEmail(), user.getEmailCode());
        if (dataVo != null) return dataVo;

        if (userService.register(user)) {
            return DataVo.ok("注册成功");
        } else {
            return DataVo.error("注册失败");
        }
    }

    //登录获取token
    @PostMapping("/getToken")
    public DataVo<TokenVo> getToken(@RequestBody LoginVo loginVo,
                                    HttpSession session) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getEmail, loginVo.getEmail());
        User user = userService.getOne(queryWrapper);
        //判断用户存在
        if (user == null) {
            return DataVo.error(DataVoCodeConstant.USER_IS_NOT_EXIST, "用户不存在");
        }
        //判断用户账号是否正常
        int status = user.getUserStatusId();
        if (status != 0) {
            return DataVo.error(DataVoCodeConstant.USER_IS_ABNORMAL, "用户状态非正常");
        }

        //校验
        if (loginVo.getPassword() != null) {
            //判断验证码
            String captcha = (String) session.getAttribute("captcha");
            if (!new MathGenerator().verify(captcha, loginVo.getCode())) {
                return DataVo.error(DataVoCodeConstant.CODE_ERROR, "验证码错误");
            }
            //判断密码
            if (!passwordEncoder.matches(loginVo.getPassword(), user.getPassword())) {
                return DataVo.error(DataVoCodeConstant.USER_PASSWORD_ERROR, "密码错误");
            }
        } else {
            //邮箱登录
            DataVo dataVo = emailUtil.checkEmailCode(session, loginVo.getEmail(), loginVo.getEmailCode());
            if (dataVo != null) return dataVo;
        }

        //保存token
        Map<String, Object> map = new HashMap<>();
        map.put("userId", user.getUserId());
        map.put("role", user.getRole());
        String token = jwtUtil.createToken(map, user.getUsername());
        TokenVo tokenVo = new TokenVo(token, user.getRole());
        return DataVo.ok(tokenVo);
    }

    //忘记密码
    @PutMapping("/resetPassword")
    public DataVo<String> resetPassword(@RequestBody @Valid ResetPwdVo resetPwdVo, HttpSession session) {
        User user = userService.getOne(new LambdaQueryWrapper<User>()
                .select(User::getUserId)
                .eq(User::getEmail, resetPwdVo.getEmail()));
        if (user == null) {
            return DataVo.error(DataVoCodeConstant.USER_IS_NOT_EXIST, "用户不存在");
        }

        DataVo<String> dataVo = emailUtil.checkEmailCode(session, resetPwdVo.getEmail(), resetPwdVo.getEmailCode());
        if (dataVo != null) return dataVo;

        user.setPassword(passwordEncoder.encode(resetPwdVo.getNewPassword()));
        if (userService.updateById(user)) {
            messageUtil.sendSystemMessage(user.getUserId(), "忘记密码成功", "密码已重置，请妥善保管", null);
            return DataVo.ok("密码重置成功!");
        }
        return DataVo.error("密码重置失败!");

    }

    //获取用户信息
    @GetMapping("/userInfo")
    public DataVo<User> getUserInfo() {
        Long userId = UserContextHolder.getUserId();
        User user = userService.getUserInfo(userId);
        if (user != null) {
            user.setPassword(null);
            return DataVo.ok(user);
        }
        return DataVo.error(DataVoCodeConstant.USER_IS_NOT_EXIST, "用户不存在");
    }

    //更新个人信息
    @PutMapping("/userInfo")
    public DataVo<String> updateUserInfo(@RequestBody @Valid User userInfo) {
        //设置当前登录用户id到Dto中
        userInfo.setUserId(UserContextHolder.getUserId());
        if (userService.updateById(userInfo)) {
            return DataVo.ok("更新成功!");
        }
        return DataVo.error("更新失败!");
    }

    //修改密码
    @PutMapping("/password")
    public DataVo<String> changePassword(@RequestBody @Valid ChangePasswordDto changePasswordDto) {
        Long userId = UserContextHolder.getUserId();
        if (userService.changePassword(userId, changePasswordDto)) {
            messageUtil.sendSecurityMessage(userId, "您的账号密码已成功修改，如非本人操作请及时处理。");
            return DataVo.ok("密码修改成功!");
        }
        return DataVo.error("密码修改失败!");
    }

    //修改邮箱
    @PutMapping("/email")
    public DataVo<String> changeEmail(@RequestBody @Valid ChangeEmailDto emailDto, HttpSession session) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(User::getEmail);
        queryWrapper.eq(User::getEmail, emailDto.getNewEmail());
        if (userService.getOne(queryWrapper) != null) {
            return DataVo.error(DataVoCodeConstant.EMAIL_IS_EXIST, "邮箱已绑定其他账号");
        }
        DataVo dataVo = emailUtil.checkEmailCode(session, emailDto.getNewEmail(), emailDto.getVerifyCode());
        if (dataVo != null) return dataVo;
        //更新邮箱
        User user = new User();
        user.setUserId(UserContextHolder.getUserId());
        user.setEmail(emailDto.getNewEmail());
        if (userService.updateById(user)) {
            messageUtil.sendSecurityMessage(UserContextHolder.getUserId(), "您的账号绑定邮箱已成功修改，如非本人操作请及时处理。");
            return DataVo.ok("邮箱修改成功!");
        }
        return DataVo.error("邮箱修改失败!");
    }

    //注销账号
    @DeleteMapping("/delete")
    public DataVo<String> delete(@RequestBody @Valid DeleteDto deleteDto) {
        Long userId = UserContextHolder.getUserId();
        if (userService.delete(userId, deleteDto.getPassword(), deleteDto.getReason())) {
            return DataVo.ok("账号注销成功!");
        }
        return DataVo.error("账号注销失败!");
    }

    @GetMapping("/getHomeInfo")
    public DataVo<User> getHomeInfo(@RequestParam Long userId) {
        User user = userService.getById(userId);
        if (user != null) {
            user.setPassword(null);
            user.setRole(null);
            user.setIsDelete(null);
            return DataVo.ok(user);
        }
        return DataVo.error(DataVoCodeConstant.USER_IS_NOT_EXIST, "用户不存在");
    }

}
